﻿using Kinlo.MESDocking;
using MaterialDesignColors;
using MaterialDesignThemes.Wpf;
using Microsoft.Win32;
using NewLife.Data;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Media;
using UIWindows.Commands;
using UIWindows.Domains;
using UIWindows.Enums;
using UIWindows.GlobalStatics;
using UIWindows.Models;
using UIWindows.Tools.Helper;
using UIWindows.ViewModels.Dialogs;
using UIWindows.Views;
using XCode;
using XingLucifer.IBase.Enums;

namespace UIWindows.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        private object _viewContent;

        public object ViewContent
        {
            get { return _viewContent; }
            set => SetProperty(ref _viewContent, value);
        }
        /// <summary>
        /// 运行时间
        /// </summary>
        public DateTime RunTime { get => DateTime.Now; }

        public ObservableCollection<MenuModel> ContentList { get; set; }

        private MenuModel _selectedItem;

        public MenuModel SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                if (value != null && _selectedItem != value)
                {
                    var ucs = ObjectContainer.ResolveSingleton<UserConfigStatic>();
                    //if (value.Name == "系统配置" && ucs.LoginUser.Level != AuthorityTypes.超级管理员)
                    //{
                    //    "此页面不可操作！！！".MessageDialogs(MessageLevelType.警告, false, PopUpTypes.Global);
                    //    _selectedItem = null;
                    //    return;
                    //}
                    if (value.Name == "主 页" || ucs.LoginUser.Name != "未登录")
                    {
                        _selectedItem = value;
                        ViewContent = ObjectContainer.ResolvePage(value.Name);
                    }
                    else
                    {
                        "请登录，方可继续操作".MessageDialogs(MessageLevelType.警告, false, PopUpTypes.Global);
                        _selectedItem = null;
                    }
                }
            }
        }

        public UserConfigStatic UserConfig { get; set; }
        public GlobalStatics.SystemConfigStatic SystemConfig { get; set; }
        public ParameterStatic Parameter { get; set; }
        public MesParameterStatic MesParameter { get; set; }
        public TemporaryStatic Temporary { get; set; }
        public DeviceConfigStatic DeviceConfig { get; set; }
        private DisplayItemsStatic _displayItems;
        public MainWindowViewModel()
        {
            SystemConfig = ObjectContainer.ResolveSingleton<SystemConfigStatic>();
            UserConfig = ObjectContainer.ResolveSingleton<UserConfigStatic>();
            _displayItems = ObjectContainer.ResolveSingleton<DisplayItemsStatic>();
            Parameter = ObjectContainer.ResolveSingleton<ParameterStatic>();
            MesParameter = ObjectContainer.ResolveSingleton<MesParameterStatic>();
            Temporary = ObjectContainer.ResolveSingleton<TemporaryStatic>();
            Temporary = ObjectContainer.ResolveSingleton<TemporaryStatic>();
            DeviceConfig = ObjectContainer.ResolveSingleton<DeviceConfigStatic>();
            UserConfig.UpdateMenu += UpdateMenu;
            ContentList = new ObservableCollection<MenuModel>();
            #region 主题样式
            _topicsModel = !File.Exists(GlobalStatic.TopicsPath) ? new TopicsModel() : JsonSerializer.Deserialize<TopicsModel>(File.ReadAllText(GlobalStatic.TopicsPath, Encoding.UTF8));

            ITheme theme = _paletteHelper.GetTheme();
            _primaryColor = _topicsModel.PrimaryColor ?? theme.PrimaryMid.Color;
            _secondaryColor = _topicsModel.SecondaryColor ?? theme.SecondaryMid.Color;
            if (theme is Theme internalTheme && internalTheme.ColorAdjustment != null)
            {
                internalTheme.ColorAdjustment.Colors = ColorSelection.All;
            }
            SelectedColor = _topicsModel.PrimaryColor;
            ChangeCustomColor((Color)_primaryColor);
            _paletteHelper.ApplyBase(_topicsModel.IsDarkTheme);
            #endregion
            foreach (var item in ObjectContainer.GetMenuList(AuthorityTypes.ALL))
            {
                if (!_displayItems.RoleInit.Any(x => x.RoleName == item.Name) && item.Name != "系统配置")
                {
                    _displayItems.RoleInit.Add(new RoleInitModel()
                    {
                        IsEnable = true,
                        Authority = AuthorityTypes.操作员,
                        Category = "菜单",
                        RoleName = item.Name,
                    });
                    _displayItems.RoleInit.Add(new RoleInitModel()
                    {
                        IsEnable = true,
                        Authority = AuthorityTypes.工艺,
                        Category = "菜单",
                        RoleName = item.Name,
                    });
                    _displayItems.RoleInit.Add(new RoleInitModel()
                    {
                        IsEnable = true,
                        Authority = AuthorityTypes.设备,
                        Category = "菜单",
                        RoleName = item.Name,
                    });
                }
            }
            UpdateMenu(AuthorityTypes.ALL);

        }

        /// <summary>
        /// 更新菜单
        /// </summary>
        /// <param name="authority"></param>
        public void UpdateMenu(AuthorityTypes authority)
        {
            ContentList.Clear();
            foreach (var item in ObjectContainer.GetMenuList(authority))
            {
                if (_displayItems.RoleInit.Any(x => x.RoleName == item.Name && x.Authority == authority && x.IsEnable)
                    || AuthorityTypes.ALL == authority
                    || AuthorityTypes.管理员 == authority
                    || AuthorityTypes.超级管理员 == authority)
                {
                    ContentList.Add(item);
                }
            }
            if (ContentList.Count > 0) SelectedItem = ContentList[0];
        }

        public DelegateCommand HelperButton => new DelegateCommand(() =>
        {
            _ = MaterialDesignThemes.Wpf.DialogHost.Show(new Views.Dialogs.LoadingDialogs(), PopUpTypes.Global.ToString()).ConfigureAwait(false);
        });

        public DelegateCommand Login => new DelegateCommand(() =>
        {
            _ = DialogHost.Show(new Views.Dialogs.LoginDialogs() { DataContext = new LoginDialogsViewModel(UserConfig) }, PopUpTypes.Global.ToString()).ConfigureAwait(false);
        });
        private IMESInteraction _interaction;
        public DelegateCommand<Button> PerformTask => new DelegateCommand<Button>(async sender =>
        {
            if (SystemConfig.SCM.PerformTaskName == null)
            {
                SystemConfig.SCM.PerformTaskName = sender;
            }
            var serviceList = Temporary.LinkList.FirstOrDefault(x => x.ServiceName == "设备状态");
            if (serviceList != null && !serviceList.Status)
            {
                _ = "有设备网线通信不上,查看日志系统输出信息,检查对应设备网线连接!!!".MessageDialogs(MessageLevelType.警告, false, PopUpTypes.Global);
                return;
            }
            _ = DialogHost.Show(new Views.Dialogs.LoadingDialogs(), PopUpTypes.Global.ToString()).ConfigureAwait(false);
            #region 上传开机参数
            if (Parameter.DecideParameter.EnableMES && SystemConfig.SCM.PerformTaskName.Content.ToString() == "    运  行    ")
            {
                if (!Temporary.Is_Mes_Login
                || string.IsNullOrEmpty(Parameter.CollectionItemsParameter.WorkOrder) ||
                string.IsNullOrEmpty(Parameter.CollectionItemsParameter.BatchElectrolyte))
                {
                    if (DialogHost.IsDialogOpen(PopUpTypes.Global.ToString()))
                        DialogHost.Close(PopUpTypes.Global.ToString());
                    _ = "带MES启动时请确保以下信息完善：\r\n\r\n1、MES已登陆；\r\n2、获取工单；   \r\n3、已上电解液！".MessageDialogs(MessageLevelType.错误, true, PopUpTypes.Global);
                    return;
                }
                else
                {
                    _ = $"带MES启动条码符合，请检查以下信息：\r\n\r\nMES登陆用户：{Temporary.Mes_Account}；\r\n工单号:{Parameter.CollectionItemsParameter.WorkOrder}\r\n电解液编号：{Parameter.CollectionItemsParameter.BatchElectrolyte}".MessageDialogs(MessageLevelType.成功, true, PopUpTypes.Global);
                }
                _interaction = _interaction ?? new UploadParamInterface(DialogLogHelper.MesLog, DialogLogHelper.MESDialog);
                Dictionary<string, object> parameters = Tools.MesHelper.MesGetRunParameterBodyHelper.GetRunParameterBody(MesParameter, Parameter, DeviceConfig);
                var result = await Task.Run(() => _interaction.Interaction(Parameter.MESParameter.BaseUrl + Parameter.MESParameter.EquipUploadParamRoute,
                       Parameter.MESParameter.EquipUploadParamTime,
                       Parameter.MESParameter.EquipUploadParamNumber, DateTime.Now, null, parameters) == ResultTypes.合格);
                if (!result)
                {
                    if (DialogHost.IsDialogOpen(PopUpTypes.Global.ToString()))
                        DialogHost.Close(PopUpTypes.Global.ToString());
                    return;
                }
            }

            #endregion

            if (SystemConfig.SCM.PerformTaskName.Content.ToString() == "    运  行    ")
            {
                if (await Services.TaskService.Instance.SwitchOn())
                {
                    SystemConfig.SCM.PerformTaskName.Content = "    停  止    ";
                    if (DialogHost.IsDialogOpen(PopUpTypes.Global.ToString())) DialogHost.Close(PopUpTypes.Global.ToString());
                }
            }
            else
            {
                Services.TaskService.Instance.SwitchOFF();
            }
        });

        /// <summary>
        /// 清除计时
        /// </summary>
        public DelegateCommand ClearTime => new DelegateCommand(() =>
        {
            var model = ObjectContainer.ResolveSingleton<HomeStatic>();
            model.EquipmentTime.Run = 0;
            model.EquipmentTime.Manual = 0;
            model.EquipmentTime.Error = 0;
            model.SaveEquipmentTime();
        });

        public DelegateCommand ExitLogin => new DelegateCommand(() => UserConfig.ExitLogin());

        /// <summary>
        /// 清除NG数据
        /// </summary>
        public DelegateCommand ClearStatisticsData => new DelegateCommand(() =>
        {
            var model = ObjectContainer.ResolveSingleton<HomeStatic>();
            model.ChartData.OV_AfterWeighingPassingRate.Value = 1;
            model.ChartData.AfterWeighingPassingRate = 1;
            model.ChartData.OV_LessLiquid.Value = 0;
            model.ChartData.NG_LessLiquid = 0;
            model.ChartData.OV_MultiLiquid.Value = 0; model.ChartData.NG_MultiLiquid = 0;
            model.ChartData.OV_LiquidInjection_PassingRate.Value = 1;
            model.ChartData.LiquidInjection_PassingRate = 1;
            model.ChartData.NG_ScanCode = 0;
            model.ChartData.Total_Inbound = 0;
            model.ChartData.NG_ShortCircuit = 0;
            model.ChartData.NG_BeforeWeighin = 0;
            model.ChartData.NG_FrontGlueNail = 0;
            model.ChartData.NG_RearGlueNail = 0;
            model.ChartData.NG_AfterScanCode = 0;
            model.ChartData.NG_LeakDetection = 0;
            model.ChartData.Total_LiquidInjection = 0;
            model.ChartData.Total_GlueNail = 0;
            model.ChartData.GlueNailPassingRate = 0;

            model.ChartData.NG_AfterScanCode = 0;
            model.ChartData.Total_AfterInbound = 0;

            model.ChartData.NG_Insulation = 0;

            model.SaveChartData();
        });

        #region 主题相关

        private readonly PaletteHelper _paletteHelper = new PaletteHelper();

        private ColorScheme _activeScheme;
        public ColorScheme ActiveScheme
        {
            get => _activeScheme;
            set
            {
                if (_activeScheme != value)
                {
                    _activeScheme = value;
                    OnPropertyChanged();
                }
            }
        }

        private Color? _selectedColor;
        public Color? SelectedColor
        {
            get => _selectedColor;
            set
            {
                if (_selectedColor != value)
                {
                    _selectedColor = value;
                    OnPropertyChanged();
                    var currentSchemeColor = ActiveScheme switch
                    {
                        ColorScheme.Primary => _primaryColor,
                        ColorScheme.Secondary => _secondaryColor,
                        ColorScheme.PrimaryForeground => _primaryForegroundColor,
                        ColorScheme.SecondaryForeground => _secondaryForegroundColor,
                        _ => throw new NotSupportedException($"{ActiveScheme} is not a handled ColorScheme.. Ye daft programmer!")
                    };
                    if (_selectedColor != currentSchemeColor && value is Color color)
                    {
                        ChangeCustomColor(color);
                        _topicsModel.PrimaryColor = _primaryColor;
                        _topicsModel.SecondaryColor = _secondaryColor;
                        Save();
                    }
                }
            }
        }

        public IEnumerable<ISwatch> Swatches { get; } = SwatchHelper.Swatches;

        private void ChangeCustomColor(object obj)
        {
            var color = (Color)obj;

            if (ActiveScheme == ColorScheme.Primary)
            {
                _paletteHelper.ChangePrimaryColor(color);
                _primaryColor = color;
            }
            else if (ActiveScheme == ColorScheme.Secondary)
            {
                _paletteHelper.ChangeSecondaryColor(color);
                _secondaryColor = color;
            }
            else if (ActiveScheme == ColorScheme.PrimaryForeground)
            {
                SetPrimaryForegroundToSingleColor(color);
                _primaryForegroundColor = color;
            }
            else if (ActiveScheme == ColorScheme.SecondaryForeground)
            {
                SetSecondaryForegroundToSingleColor(color);
                _secondaryForegroundColor = color;
            }
        }

        private Color? _primaryColor;

        private Color? _secondaryColor;

        private Color? _primaryForegroundColor;

        private Color? _secondaryForegroundColor;

        public DelegateCommand<object> ChangeHueCommand => new DelegateCommand<object>(obj =>
        {
            var hue = (Color)obj;

            SelectedColor = hue;
            if (ActiveScheme == ColorScheme.Primary)
            {
                _paletteHelper.ChangePrimaryColor(hue);
                _primaryColor = hue;
                _primaryForegroundColor = _paletteHelper.GetTheme().PrimaryMid.GetForegroundColor();
            }
            else if (ActiveScheme == ColorScheme.Secondary)
            {
                _paletteHelper.ChangeSecondaryColor(hue);
                _secondaryColor = hue;
                _secondaryForegroundColor = _paletteHelper.GetTheme().SecondaryMid.GetForegroundColor();
            }
            else if (ActiveScheme == ColorScheme.PrimaryForeground)
            {
                SetPrimaryForegroundToSingleColor(hue);
                _primaryForegroundColor = hue;
            }
            else if (ActiveScheme == ColorScheme.SecondaryForeground)
            {
                SetSecondaryForegroundToSingleColor(hue);
                _secondaryForegroundColor = hue;
            }
        });

        private void SetPrimaryForegroundToSingleColor(Color color)
        {
            ITheme theme = _paletteHelper.GetTheme();

            theme.PrimaryLight = new ColorPair(theme.PrimaryLight.Color, color);
            theme.PrimaryMid = new ColorPair(theme.PrimaryMid.Color, color);
            theme.PrimaryDark = new ColorPair(theme.PrimaryDark.Color, color);

            _paletteHelper.SetTheme(theme);
        }

        private void SetSecondaryForegroundToSingleColor(Color color)
        {
            ITheme theme = _paletteHelper.GetTheme();

            theme.SecondaryLight = new ColorPair(theme.SecondaryLight.Color, color);
            theme.SecondaryMid = new ColorPair(theme.SecondaryMid.Color, color);
            theme.SecondaryDark = new ColorPair(theme.SecondaryDark.Color, color);

            _paletteHelper.SetTheme(theme);
        }

        public bool IsDarkTheme
        {
            get { return _topicsModel.IsDarkTheme; }
            set
            {
                _topicsModel.IsDarkTheme = value;
                _paletteHelper.ApplyBase(_topicsModel.IsDarkTheme);
                Save();
            }
        }

        private TopicsModel _topicsModel;
        private void Save() => File.WriteAllText(GlobalStatic.TopicsPath, JsonSerializer.Serialize(_topicsModel, GlobalStatic.Options), Encoding.UTF8);

        #endregion

        #region 更新模块
        /// <summary>
        /// 更新更哪里
        /// </summary>
        static string toDirectoryPath = Environment.CurrentDirectory;
        /// <summary>
        /// 主程序路径
        /// </summary>
        static string mainProgramFilePath = @$"{toDirectoryPath}\UIWindows.exe";
        /// <summary>
        /// 更新文件
        /// </summary>
        static string fromFilePath = string.Empty;

        /// <summary>
        /// 备份路径
        /// </summary>
        static string backupsDirectoryPath = @$"{new DirectoryInfo(toDirectoryPath).Parent.FullName}\WeightAppBackups";
        /// <summary>
        /// 备份排除文件,以 -x! 开头，可多个文件或文件夹
        /// </summary>
        static string backupIgnore = @$" -x!MESlog -x!logs -x!Log -x!TableData ";

        /// <summary>
        /// 更新时排除的文件,以 -x! 开头，可多个文件或文件夹
        /// </summary>
        static string updateIgnore = @$" -x!config -x!AZUpdate -x!appsettings.json ";
        /// <summary>
        /// 运行更新程序位置
        /// </summary>
        static string updateApp = @$"{toDirectoryPath}\AZUpdate\Kinlo.AZUpdate.exe";

        public DelegateCommand UpdateCmd => new DelegateCommand(() =>
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Multiselect = false;//该值确定是否可以选择多个文件
            dialog.Title = "请选择文件";
            dialog.Filter = "压缩文件(*.7z;*.zip;*.rar)|*.7z;*.zip;*.rar";
            var v = dialog.ShowDialog();
            if (v == true)
            {
                var temporary = ObjectContainer.ResolveSingleton<TemporaryStatic>();
                if (temporary.IsRunStatus)
                {
                    Services.TaskService.Instance.SwitchOFF();
                    while (temporary.IsRunStatus)
                    {
                        Thread.Sleep(500);
                    }
                }

                fromFilePath = dialog.FileName;
                Process.Start(updateApp, new string[] { "1", mainProgramFilePath, fromFilePath, toDirectoryPath, backupsDirectoryPath, backupIgnore, updateIgnore });
                Environment.Exit(0);
            }
        });
        public DelegateCommand BackupCmd => new DelegateCommand(() =>
        {
            Process.Start(updateApp, new string[] { "2", mainProgramFilePath, fromFilePath, toDirectoryPath, backupsDirectoryPath, backupIgnore, updateIgnore });
        });
        public DelegateCommand RevertCmd => new DelegateCommand(() =>
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.InitialDirectory = backupsDirectoryPath;
            dialog.Multiselect = false;//该值确定是否可以选择多个文件
            dialog.Title = "请选择文件";
            dialog.Filter = "压缩文件(*.7z;*.zip;*.rar)|*.7z;*.zip;*.rar";
            var v = dialog.ShowDialog();
            if (v == true)
            {
                var temporary = ObjectContainer.ResolveSingleton<TemporaryStatic>();
                if (temporary.IsRunStatus)
                {
                    Services.TaskService.Instance.SwitchOFF();
                    while (temporary.IsRunStatus)
                    {
                        Thread.Sleep(500);
                    }
                }
                fromFilePath = dialog.FileName;
                Process.Start(updateApp, new string[] { "3", mainProgramFilePath, fromFilePath, toDirectoryPath, backupsDirectoryPath, backupIgnore, updateIgnore });
                Environment.Exit(0);
            }
        });

        ManualWeight _manualWeight;
        public DelegateCommand<System.Windows.Window> TonicCommand => new DelegateCommand<System.Windows.Window>((win) =>
        {
            //打开补液窗口
            if (!IsWindowOpen<ManualWeight>())
            {
                _manualWeight = new ManualWeight();

                //显示在右下角
                double xpos = win.Left + win.Width - _manualWeight.Width - 10;
                double ypos = win.Top + win.Height - _manualWeight.Height - 10;
                _manualWeight.Left = xpos;
                _manualWeight.Top = ypos;

                _manualWeight.DataContext = new ManualWeightViewModel(Temporary, Parameter, SystemConfig, ObjectContainer.ResolveSingleton<DeviceConfigStatic>());
                _manualWeight.Show();
            }
            else
            {
                _manualWeight.Activate();
            }
        });

        SupplementaryDataView _supplementaryDataView;
        public DelegateCommand ShowRestoreDataCMD => new DelegateCommand(() =>
        {
            if (!IsWindowOpen<ManualWeight>())
            {
                _supplementaryDataView = new SupplementaryDataView();
                _supplementaryDataView.DataContext = new SupplementaryDataViewModel(_displayItems, Parameter, Temporary);
                _supplementaryDataView.Show();
            }
            else
            {
                _supplementaryDataView.Activate();
            }
        });
        public static bool IsWindowOpen<T>(string name = null) where T : System.Windows.Window
        {
            var windows = System.Windows.Application.Current.Windows.OfType<T>();
            return string.IsNullOrEmpty(name) ?
             System.Windows.Application.Current.Windows.OfType<T>().Any() :
             System.Windows.Application.Current.Windows.OfType<T>().Any(w => w.Name.Equals(name));
        }
        #endregion
    }
}
